package com.example.demo.service.impl;

import com.example.demo.entity.CopyrightEntity;
import com.example.demo.entity.CopyrightTradeRequestEntity;
import com.example.demo.model.CopyrightTradeRequestInfo;
import com.example.demo.repository.CopyrightRepository;
import com.example.demo.repository.CopyrightTradeRequestRepository;
import com.example.demo.service.CopyrightService;
import com.example.demo.service.CopyrightTradeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/**
 * 版权交易服务实现类
 */
@Slf4j
@Service
public class CopyrightTradeServiceImpl implements CopyrightTradeService {
    
    @Autowired
    private CopyrightService copyrightService;
    
    @Autowired
    private CopyrightRepository copyrightRepository;
    
    @Autowired
    private CopyrightTradeRequestRepository tradeRepository;
    
    /**
     * 发起交易请求
     * @param fromAddress 发起方地址
     * @param toAddress 接收方地址
     * @param blockchainId 版权ID
     * @param requestType 请求类型：目前仅支持 2-转让
     * @return 交易请求ID
     */
    @Override
    @Transactional
    public Long createTradeRequest(String fromAddress, String toAddress, String blockchainId, Integer requestType) {
        log.info("创建交易请求 - 从: {}, 到: {}, 版权ID: {}, 类型: {}", 
                fromAddress, toAddress, blockchainId, requestType);
                
        // 验证请求类型（只支持转让）
        if (requestType != 2) {
            throw new RuntimeException("不支持的请求类型: " + requestType + "，目前仅支持转让(2)");
        }
                
        // 获取版权信息，验证所有权
        CopyrightEntity entity = copyrightRepository.findByBlockchainId(blockchainId)
                .orElseThrow(() -> new RuntimeException("版权不存在: " + blockchainId));
                
        if (!entity.getOwnerAddress().equalsIgnoreCase(fromAddress)) {
            throw new RuntimeException("您不是该版权的所有者，无法发起交易请求");
        }
        
        // 验证版权有效性
        if (!entity.getIsValid()) {
            throw new RuntimeException("该版权已失效，无法发起交易请求");
        }
        
        // 检查是否已有未处理的请求
        List<CopyrightTradeRequestEntity> existingRequests = 
                tradeRepository.findByCopyrightIdAndToAddressAndStatusOrderByCreateTimeDesc(
                        entity.getId(), toAddress, 0);
        
        if (!existingRequests.isEmpty()) {
            throw new RuntimeException("已存在未处理的交易请求，请等待对方处理");
        }
        
        // 创建交易请求
        CopyrightTradeRequestEntity request = 
                new CopyrightTradeRequestEntity(entity.getId(), fromAddress, toAddress, requestType);
        
        // 保存请求
        request = tradeRepository.save(request);
        log.info("交易请求创建成功 - ID: {}", request.getId());
        
        return request.getId();
    }
    
    /**
     * 接受交易请求
     * @param requestId 请求ID
     * @param toAddress 接收方地址
     * @return 处理结果
     */
    @Override
    @Transactional
    public boolean acceptTradeRequest(Long requestId, String toAddress) {
        log.info("接受交易请求 - ID: {}, 接收方: {}", requestId, toAddress);
        
        // 获取请求
        CopyrightTradeRequestEntity request = tradeRepository.findById(requestId)
                .orElseThrow(() -> new RuntimeException("交易请求不存在: " + requestId));
                
        // 验证接收方
        if (!request.getToAddress().equalsIgnoreCase(toAddress)) {
            throw new RuntimeException("您不是该交易请求的接收方，无法处理");
        }
        
        // 验证状态
        if (request.getStatus() != 0) {
            throw new RuntimeException("该交易请求已被处理，当前状态: " + 
                    (request.getStatus() == 1 ? "已接受" : "已拒绝"));
        }
        
        // 获取版权信息
        CopyrightEntity copyright = copyrightRepository.findById(request.getCopyrightId())
                .orElseThrow(() -> new RuntimeException("版权不存在: " + request.getCopyrightId()));
                
        // 验证所有权
        if (!copyright.getOwnerAddress().equalsIgnoreCase(request.getFromAddress())) {
            throw new RuntimeException("发起方不再是该版权的所有者，无法完成交易");
        }
        
        try {
            // 根据请求类型执行不同操作
            // 转让
            if (request.getRequestType() == 2) {
                // 执行区块链转让操作
                String txHash = executeTransferAndGetTxHash(
                        request.getFromAddress(),
                        new BigInteger(copyright.getBlockchainId()),
                        request.getToAddress());
                        
                // 更新请求状态并保存交易哈希
                request.updateStatus(1, "交易成功，版权已转让");
                request.setTransactionHash(txHash);
                tradeRepository.save(request);
                
                log.info("版权转让成功 - 版权ID: {}, 交易哈希: {}", copyright.getBlockchainId(), txHash);
                return true;
            } else {
                throw new RuntimeException("不支持的请求类型: " + request.getRequestType() + "，目前仅支持转让(2)");
            }
        } catch (Exception e) {
            log.error("处理交易请求失败: {}", e.getMessage(), e);
            
            // 更新请求状态
            request.updateStatus(2, "交易失败: " + e.getMessage());
            tradeRepository.save(request);
            
            throw e;
        }
    }
    
    /**
     * 执行转让操作并获取交易哈希
     */
    private String executeTransferAndGetTxHash(String fromAddress, BigInteger copyrightId, String toAddress) {
        try {
            // 创建一个内部类来捕获交易哈希
            final String[] txHash = new String[1];
            
            // 添加监听器，保存交易Hash
            copyrightService.addTransactionReceiptListener(receipt -> {
                if (receipt != null && receipt.isStatusOK()) {
                    txHash[0] = receipt.getTransactionHash();
                }
            });
            
            try {
                // 执行转让操作
                // 这里的ID是请求ID
                copyrightService.transferCopyright(String.valueOf(copyrightId), fromAddress, toAddress);
            } finally {
                // 无论成功失败，都移除监听器避免内存泄漏
                copyrightService.removeTransactionReceiptListener();
            }
            
            // 如果没有获取到交易哈希，记录警告
            if (txHash[0] == null) {
                log.warn("转让成功但未能捕获交易哈希");
                return "transfer-success-" + System.currentTimeMillis();
            }
            
            return txHash[0];
        } catch (Exception e) {
            log.error("执行转让操作失败: {}", e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 拒绝交易请求
     * @param requestId 请求ID
     * @param toAddress 接收方地址
     * @param reason 拒绝原因
     * @return 处理结果
     */
    @Override
    @Transactional
    public boolean rejectTradeRequest(Long requestId, String toAddress, String reason) {
        log.info("拒绝交易请求 - ID: {}, 接收方: {}, 原因: {}", requestId, toAddress, reason);
        
        // 获取请求
        CopyrightTradeRequestEntity request = tradeRepository.findById(requestId)
                .orElseThrow(() -> new RuntimeException("交易请求不存在: " + requestId));
                
        // 验证接收方
        if (!request.getToAddress().equalsIgnoreCase(toAddress)) {
            throw new RuntimeException("您不是该交易请求的接收方，无法处理");
        }
        
        // 验证状态
        if (request.getStatus() != 0) {
            throw new RuntimeException("该交易请求已被处理，当前状态: " + 
                    (request.getStatus() == 1 ? "已接受" : "已拒绝"));
        }
        
        // 更新请求状态
        request.updateStatus(2, "交易被拒绝: " + reason);
        tradeRepository.save(request);
        
        log.info("交易请求已拒绝 - ID: {}", requestId);
        
        return true;
    }
    
    /**
     * 获取发起的交易请求
     * @param fromAddress 发起方地址
     * @return 交易请求列表
     */
    @Override
    public List<CopyrightTradeRequestInfo> getSentTradeRequests(String fromAddress) {
        log.info("获取用户发起的交易请求 - 用户: {}", fromAddress);
        
        List<CopyrightTradeRequestEntity> requests = 
                tradeRepository.findByFromAddressOrderByCreateTimeDesc(fromAddress);
                
        return convertToInfoList(requests);
    }
    
    /**
     * 获取收到的交易请求
     * @param toAddress 接收方地址
     * @return 交易请求列表
     */
    @Override
    public List<CopyrightTradeRequestInfo> getReceivedTradeRequests(String toAddress) {
        log.info("获取用户收到的交易请求 - 用户: {}", toAddress);
        
        List<CopyrightTradeRequestEntity> requests = 
                tradeRepository.findByToAddressOrderByCreateTimeDesc(toAddress);
                
        return convertToInfoList(requests);
    }
    
    /**
     * 获取待处理的交易请求
     * @param toAddress 接收方地址
     * @return 交易请求列表
     */
    @Override
    public List<CopyrightTradeRequestInfo> getPendingTradeRequests(String toAddress) {
        log.info("获取用户未处理的交易请求 - 用户: {}", toAddress);
        
        List<CopyrightTradeRequestEntity> requests = 
                tradeRepository.findByToAddressAndStatusOrderByCreateTimeDesc(toAddress, 0);
                
        return convertToInfoList(requests);
    }
    
    /**
     * 获取交易请求详情
     * @param requestId 请求ID
     * @return 交易请求详情
     */
    @Override
    public CopyrightTradeRequestInfo getTradeRequestDetail(Long requestId) {
        log.info("获取交易请求详情 - ID: {}", requestId);
        
        CopyrightTradeRequestEntity request = tradeRepository.findById(requestId)
                .orElseThrow(() -> new RuntimeException("交易请求不存在: " + requestId));
                
        CopyrightTradeRequestInfo info = CopyrightTradeRequestInfo.fromEntity(request);
        
        // 补充版权信息
        try {
            CopyrightEntity copyright = copyrightRepository.findById(request.getCopyrightId())
                    .orElse(null);
                    
            if (copyright != null) {
                info.setBlockchainId(copyright.getBlockchainId());
                info.setCopyrightInfo(copyrightService.convertEntityToInfo(copyright));
            }
        } catch (Exception e) {
            log.error("获取版权信息失败: {}", e.getMessage());
        }
        
        return info;
    }
    
    /**
     * 将实体列表转换为信息对象列表
     */
    private List<CopyrightTradeRequestInfo> convertToInfoList(List<CopyrightTradeRequestEntity> entities) {
        List<CopyrightTradeRequestInfo> result = new ArrayList<>();
        
        for (CopyrightTradeRequestEntity entity : entities) {
            CopyrightTradeRequestInfo info = CopyrightTradeRequestInfo.fromEntity(entity);
            
            // 补充版权信息
            try {
                CopyrightEntity copyright = copyrightRepository.findById(entity.getCopyrightId())
                        .orElse(null);
                        
                if (copyright != null) {
                    info.setBlockchainId(copyright.getBlockchainId());
                    // 加载完整版权信息
                    info.setCopyrightInfo(copyrightService.convertEntityToInfo(copyright));
                }
            } catch (Exception e) {
                log.error("获取版权信息失败: {}", e.getMessage());
            }
            
            result.add(info);
        }
        
        return result;
    }
} 